package com.config;

import com.pojo.SysRight;
import com.service.SysRightService;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Configuration
public class ShiroConfig {
    @Autowired
    SysRightService sysRightService;

    /**
     * 加密方式
     * @return
     */
    @Bean
    public CredentialsMatcher getHashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher=new HashedCredentialsMatcher();
        //加密算法名称
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        //加密次数
        hashedCredentialsMatcher.setHashIterations(2);
        return hashedCredentialsMatcher;
    }
    /**
     * 将自定义域交给spring管理
     * @return
     */
    @Bean
    public Realm getRealm(){
        CustomRealm realm=new CustomRealm();
        //设置域开启授权缓存
        realm.setAuthorizationCachingEnabled(true);
        realm.setAuthorizationCacheName("authorizationCacheName");


//        realm.setAuthenticationCachingEnabled(true);

        //设置加密方式
        realm.setCredentialsMatcher(getHashedCredentialsMatcher());
        return realm;
    }

    //配置RedisManager
    public RedisManager getRedisManager(){
        RedisManager redisManager=new RedisManager();
        return redisManager;
    }

    //Redis缓存管理器
//    @Bean
    public RedisCacheManager getCacheManager(){
        RedisCacheManager redisCacheManager=new RedisCacheManager();
        redisCacheManager.setRedisManager(getRedisManager());
        //设置shiro中的标识属性dd
        redisCacheManager.setPrincipalIdFieldName("usrId");
        return redisCacheManager;
    }

    //配置SessionDao
    public RedisSessionDAO getRedisSessionDao(){
        RedisSessionDAO redisSessionDAO=new RedisSessionDAO();
        redisSessionDAO.setRedisManager(getRedisManager());
        return redisSessionDAO;
    }

//    //会话管理器
    public DefaultWebSessionManager getDefaultWebSessionManager(){
        DefaultWebSessionManager defaultWebSessionManager=new DefaultWebSessionManager();
        defaultWebSessionManager.setSessionDAO(getRedisSessionDao());
        //URL不显示sessionId
        defaultWebSessionManager.setSessionIdUrlRewritingEnabled(false);
        return defaultWebSessionManager;
    }

    /**
     * 将自定义域注入到securityManager用于后续认证授权数据对比
     */
    @Bean
    public SecurityManager getSecurityManager(){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager(getRealm());
        defaultWebSecurityManager.setCacheManager(getCacheManager());
        defaultWebSecurityManager.setSessionManager(getDefaultWebSessionManager());
        return defaultWebSecurityManager;
    }

    /**
     * 将SecurityManager注入shiro过滤器，用于后续的认证授权等功能
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
        ShiroFilterFactoryBean filterFactoryBean=new ShiroFilterFactoryBean();
        filterFactoryBean.setSecurityManager(getSecurityManager());
        //配置资源认证规则
        Map<String,String> urlMap=new LinkedHashMap<>();
        urlMap.put("/css/*", "anon");
        urlMap.put("/js/*", "anon");
        urlMap.put("/fonts/*", "anon");
        urlMap.put("/images/*", "anon");
        urlMap.put("/localcss/*", "anon");
        urlMap.put("/localjs/*", "anon");
        urlMap.put("/doLogin", "anon");
        urlMap.put("/logout", "anon");
        //登录页面
//        urlMap.put("/", "anon");
        //从数据库上获取 动态
        
        List<SysRight> rightList=sysRightService.list();
        for (SysRight sysRight:rightList) {
            if (StringUtils.hasText(sysRight.getRightUrl())){
                urlMap.put(sysRight.getRightUrl(), "perms["+sysRight.getRightCode()+"]");
            }
        }

        //除了上面配置的路径的规则其他请求必须认证通过才可访问
        urlMap.put("/**", "authc");
        filterFactoryBean.setFilterChainDefinitionMap(urlMap);
        filterFactoryBean.setLoginUrl("/");
        //设置权限不足页面
        filterFactoryBean.setUnauthorizedUrl("/403");
        return filterFactoryBean;
    }
}
